package com.hereway.core.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.hereway.core.context.PageBean;

/**
 *对Hibernate的封装
 *@author Kevin.H
 *@version   V1.0
 */
public abstract class BaseHibernateDAO<T, PK extends Serializable> extends HibernateDaoSupport
		implements IBaseDAO<T, PK> {
	private Class<T> persistentClass;
	protected Log log = LogFactory.getLog(this.getClass());
      
	@SuppressWarnings("unchecked")
	public BaseHibernateDAO() {
		//this.getHibernateTemplate().setCacheQueries(true);
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	//为父类HibernateDaoSupport注入sessionFactory的值
    @Resource(name="sessionFactory")
    public void setSuperSessionFactory(SessionFactory sessionFactory){
        super.setSessionFactory(sessionFactory);
    }

	@Override
	public List<T> loadAll() {
		//this.getHibernateTemplate().setCacheQueries(false);
		return getHibernateTemplate().loadAll(persistentClass);
	}
	
	@Override
	public List<T> loadAll(final PageBean page) {
		return find("", "", page);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> find(final String whereStr, final String orderStr, final PageBean page) {
		return getHibernateTemplate().executeFind(new HibernateCallback()
		{
			public Object doInHibernate(Session session) throws HibernateException, SQLException{
				
				String list = "from " + persistentClass.getSimpleName() + " t " + whereStr + " " + orderStr;
				Query qry = session.createQuery(list);
				if(page == null){
					return qry.list();
				}
				else{
					Object[] paramsArr = null;
					String count = "Select count(t) from " + persistentClass.getSimpleName() + " t " + whereStr;
					long total = (Long) uniqueResult(count, paramsArr);
					page.setTotal(total);
					
					return getOnePageResults(session.createQuery(list), page, paramsArr);
				}
			}
		});
	}
	
	@Override
	public List<T> find(final String whereStr, final PageBean page) {
		return find(whereStr,getDefaultOrderStr(),page);
	}
	
	@Override
	public List<T> find(final String whereStr, final String orderStr){
		return find(whereStr,orderStr,null);
	}
	
	@Override
	public List<T> find(final String whereStr){
		return find(whereStr,getDefaultOrderStr());
	} 
	
	@Override
	public T load(PK id){
		return (T) getHibernateTemplate().load(persistentClass, id);
	}

	@Override
	public T get(PK id){
		return (T) getHibernateTemplate().get(persistentClass, id);
	}
	
	@Override
	public void save(T entity){
		getHibernateTemplate().save(entity);
	}

	@Override
	public void update(T entity){
		getHibernateTemplate().update(entity);
	}

	@Override
	public void delete(T entity){
		getHibernateTemplate().delete(entity);
	}
	
	@Override
	public void delete(List<T> list){
		getHibernateTemplate().deleteAll(list);
	}

	@Override
	public void delete(PK id){
		T entity = (T) getHibernateTemplate().load(persistentClass, id);
		if(entity != null)
			getHibernateTemplate().delete(entity);
	}
	
	@SuppressWarnings("unchecked")
	protected Object uniqueResult(final String hql, final Object[] params) {
		return getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				query.setCacheable(false);
				if (params != null)
					for (int i = 0; i < params.length; i++)
						query.setParameter(i, params[i]);
				return query.uniqueResult();
			}
		});
	}
	

	@SuppressWarnings("unchecked")
	protected List<T> getOnePageResults(Query query, PageBean page, Object[] params) {
		query.setCacheable(false);
		
		if(page != null){
			query.setFirstResult(page.getStart());
			query.setMaxResults(page.getPerPage());
		}
		if (params != null)
			for (int i = 0; i < params.length; i++)
				query.setParameter(i, params[i]);
		return query.list();
	}

	@SuppressWarnings("unchecked")
	protected List<T> getOnePageResultsForTree(Query query, PageBean page, Object[] params) {
		query.setCacheable(true);
		query.setFirstResult(page.getStart());
		query.setMaxResults(page.getPerPage());
		if (params != null)
			for (int i = 0; i < params.length; i++)
				query.setParameter(i, params[i]);
		return query.list();
	}

	/**
	 * 默认排序条件字符串，如有需要请override
	 * @return
	 */
	protected String getDefaultOrderStr(){
		return "";
	}
}
